home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / shelp.lzh / SHELP / SHELP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-31  |  22.5 KB  |  1,187 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <tos.h>
  6.  
  7.     /* io streams */
  8.         /* global um sie im fehlerfall schließen zu können */
  9. FILE *dest;
  10. FILE *source;
  11.  
  12.     /* parameter die durch kommandozeilen optionen geändert werden können */
  13.         /* definition der zu schreibenden daten */
  14. int write_function=0;
  15. int write_typedef=0;
  16. int write_define=0;
  17.         /* doppelte referenzen nur einmal schreiben */
  18. int dont_write_double=1;
  19.  
  20.         /* headerdatei für hypertext */
  21. char header_file[128]="HEADER.STG";
  22.         /* ausgabedatei */
  23. char out_file[128]="SHELP.STG";
  24.  
  25. char database[128]="Online-Hilfe zu C-Sourcen";
  26.  
  27.         /* puffergröße für typedef/funktionskopf */
  28. long buf_size=8*1024l;
  29.         /* puffergröße für namen */
  30. long names_size=64*1024l;
  31.  
  32.         /* zeiger auf puffer */
  33. char *fu;
  34. char *buffer,*b;
  35.  
  36. typedef enum {
  37.     FUNCTION=0,
  38.     TYPEDEF,
  39.     DEFINE,
  40. } NAME_TYP;
  41.  
  42. typedef struct _names {
  43.     struct _names     *next;        /* zeiger auf nächste struktur */
  44.     int             count;        /* nummer bei mehrfacheinträgen */
  45.     int             unique;        /* name eindeutig (oder erstmalig) */
  46.     NAME_TYP        typ;        /* typ des eintrags */
  47.     char             name[];
  48. } NAMES;
  49.  
  50. NAMES *names,*next;
  51. int name_count[3];                /* zaehler für eintrage der versch. typen */
  52.  
  53. /*
  54.         fehlercodes
  55. */
  56. typedef enum {
  57.     ERR_INTERNAL,
  58.     ERR_FILE,
  59.     ERR_MEMORY,
  60.     ERR_OPTIONS,
  61.     ERR_BUFFER,
  62.     ERR_NAMES,
  63.     ERR_NOFILES,
  64. } ERR_NUMS;
  65.  
  66. void do_error(ERR_NUMS error)
  67. {
  68.     switch ( error ) {
  69.       case ERR_INTERNAL:        /* should not happen */
  70.         fprintf(stderr,"Something went wrong\n");
  71.       break;
  72.       case ERR_MEMORY:
  73.           fprintf(stderr,"Speicher reicht nicht\n");
  74.       break;
  75.       case ERR_FILE:
  76.           fprintf(stderr,"Dateifehler\n");
  77.       break;
  78.       case ERR_OPTIONS:
  79.           fprintf(stderr,"unbekannte Option angegeben\n");
  80.       break;
  81.       case ERR_BUFFER:
  82.           fprintf(stderr,"Puffer für Strukturen/Funktionen voll, vergrößern mit -b \n");
  83.       break;
  84.       case ERR_NAMES:
  85.           fprintf(stderr,"Puffer für Namen voll, vergrößern mit -s \n");
  86.       break;
  87.       case ERR_NOFILES:
  88.           fprintf(stderr,"Keine Quelldateien angegeben \n");
  89.       break;
  90.     }
  91.     if ( source )
  92.         fclose(source);
  93.     if ( dest )
  94.         fclose(dest);
  95.     if ( fu )
  96.         free(fu);
  97.     if ( buffer )
  98.         free(buffer);
  99.     if ( names )
  100.         free(names);
  101.  
  102.     exit(1);
  103. }
  104.  
  105. /*
  106.     schreibe in puffer
  107. */
  108. void init_buffer(void)
  109. {
  110.     b=buffer;
  111. }
  112. void wr_buffer(char c)
  113. {
  114.     if ( b<buffer+buf_size )
  115.         *b++=c;
  116.     else
  117.         do_error(ERR_BUFFER);
  118. }
  119.  
  120. NAMES *protocol_name(char *name,NAME_TYP typ)
  121.     /*
  122.         protokolliere namen und typ in des liste 'names'
  123.     */
  124. {
  125. NAMES *act;
  126. long len;
  127. int unique=1;
  128. int count=0;
  129.  
  130.     for ( act=names; act->next!=0l; act=act->next ) {
  131.         if ( !strcmp(name,act->name) ) {
  132.             if ( dont_write_double )
  133.                 return 0l;
  134.  
  135.             if ( typ==act->typ ) {
  136.                 count=act->count+1;
  137.                 unique=act->unique;
  138.             }
  139.             else
  140.                 unique=0;
  141.         }
  142.     }
  143.  
  144.     len=sizeof(NAMES)+strlen(name)+1;
  145.     if ( len&1 )
  146.         len++;
  147.     next->next=(NAMES*)((char*)next+len);
  148.     if ( next->next>(NAMES*)((char*)names+names_size) )
  149.         do_error(ERR_NAMES);
  150.  
  151.     name_count[typ]++;
  152.     next->typ=typ;
  153.     next->count=count;
  154.     next->unique=unique;
  155.     strcpy(next->name,name);
  156.     act=next;
  157.     next=next->next;
  158.     next->next=0l;
  159.     return act;
  160. }
  161.  
  162. void get_typedef_name(char *str)
  163.     /*
  164.         ermittle namen einer typedef angabe:
  165.             zwei möglichkeiten: typedef ... name;
  166.                                 typedef ... (*name)(...);    (zeiger auf funktion)
  167.     */
  168. {
  169. char *h;
  170. int klammer=0;
  171. int something=0;
  172.  
  173.     h=buffer+strlen(buffer);
  174.     while ( h>buffer ) {
  175.         if ( isalnum(*h) || *h=='_' )
  176.             something=1;
  177.         if ( *h==')' )
  178.             klammer++;
  179.         if ( *h=='(' )
  180.             klammer--;
  181.         if ( !klammer && something && isspace(*h) )
  182.             break;
  183.         h--;
  184.     }
  185.  
  186.     while ( !isalpha(*h) && *h!='_' )
  187.         h++;
  188.  
  189.     while ( isalnum(*h) || *h=='_' )
  190.         *str++=*h++;
  191.     *str=0;
  192. }
  193.  
  194. void store_name(NAMES *name,char *file,int line,char typ)
  195.     /*
  196.         schreibe namen in zieldatei
  197.  
  198.             @node NAME
  199.             FILE file LINE nn
  200.  
  201.         wobei 'file' link auf Datei/Zeile ist
  202.         gegebenenfalls doppelte Einträge markieren
  203.     */
  204. {
  205.     fputs("@node ",dest);
  206.     fputs(name->name,dest);
  207.  
  208.     if ( name->unique ) {
  209.         if ( name->count )
  210.             fprintf(dest,".%d\n\nFILE @{%s link %s/Main %d} LINE @{B}%d@{b}\n\n",name->count,file,file,line,line);
  211.         else
  212.             fprintf(dest,"\n\nFILE @{%s link %s/Main %d} LINE @{B}%d@{b}\n\n",file,file,line,line);
  213.     }
  214.     else {
  215.         if ( name->count )
  216.             fprintf(dest,".%c%d\n\nFILE @{%s link %s/Main %d} LINE @{B}%d@{b}\n\n",typ,name->count,file,file,line,line);
  217.         else
  218.             fprintf(dest,".%c\n\nFILE @{%s link %s/Main %d} LINE @{B}%d@{b}\n\n",typ,file,file,line,line);
  219.     }
  220. }
  221.  
  222. void store_typedef(char *file,int line)
  223.     /*
  224.         schreibe typedef angaben aus buffer nach DEST
  225.     */
  226. {
  227. char str[256];
  228. NAMES *name;
  229.  
  230.  
  231.     if ( !write_typedef )
  232.         return;
  233.  
  234.     get_typedef_name(str);
  235.  
  236.     name=protocol_name(str,TYPEDEF);
  237.     if ( !name )
  238.         return;
  239.  
  240.     store_name(name,file,line,'T');
  241.  
  242.     fputs("typedef",dest);
  243.     fputs(buffer,dest);
  244.     fputs("\n\@endnode\n\n",dest);
  245. }
  246.  
  247. void copy_typedef(int *line)
  248.     /*
  249.         lese typedef angaben ein
  250.     */
  251. {
  252. enum {
  253.     C_READ,
  254.     C_COMM_1,
  255.     C_COMM_2,
  256.     C_COMM_3,
  257. } mode=C_READ;
  258. int block_cnt=0,com_cnt=0;
  259. int exit=0;
  260. char c;
  261.  
  262.     init_buffer();
  263.     do {
  264.         c=fgetc(source);
  265.         if ( c=='\n' )
  266.             (*line)++;
  267.  
  268.         switch ( mode ) {
  269.                 /* lese text */
  270.           case C_READ:
  271.             if ( c=='/' ) {            /* kommentar könnte anfangen */
  272.                 mode=C_COMM_1;
  273.             }
  274.             else if ( c=='{' )
  275.                 block_cnt++;
  276.             else if ( c=='}' )
  277.                 block_cnt--;
  278.             else if ( block_cnt==0 && c==';' )
  279.                 exit=1;
  280.           break;
  281.  
  282.                 /* lese kommentar */
  283.           case C_COMM_1:
  284.               if ( c=='*' ) {
  285.                   com_cnt++;
  286.                   mode=C_COMM_2;
  287.             }
  288.               else {
  289.                   if ( com_cnt )
  290.                       mode=C_COMM_2;
  291.                 else if ( c=='/' )
  292.                     mode=C_COMM_1;
  293.                   else
  294.                       mode=C_READ;
  295.             }
  296.           break;
  297.           case C_COMM_2:
  298.               if ( c=='*' )
  299.                   mode=C_COMM_3;
  300.             else if ( c=='/' )
  301.                 mode=C_COMM_1;
  302.           break;
  303.           case C_COMM_3:
  304.             if ( c=='/' ) {
  305.                 com_cnt--;
  306.                 if ( com_cnt==0 ) {
  307.                     mode=C_READ;
  308.                 }
  309.                 else
  310.                     mode=C_COMM_2;
  311.             }
  312.             else if ( c!='*' )
  313.                 mode=C_COMM_2;
  314.           break;
  315.         }
  316.  
  317.         wr_buffer(c);
  318.     } while ( !exit && !feof(source) );
  319.  
  320.     if ( feof(source) )
  321.         do_error(ERR_INTERNAL);
  322.  
  323.     wr_buffer(0);
  324. }
  325.  
  326. void get_define_name(char *str)
  327.     /*
  328.         ermittle namen in define-anweisung
  329.     */
  330. {
  331. char *h;
  332.  
  333.     h=buffer;
  334.     while ( isalnum(*h) || *h=='_' )
  335.         *str++=*h++;
  336.     *str=0;
  337. }
  338.  
  339. void store_define(char *file,int line)
  340.     /*
  341.         schreibe #define aus buffer nach DEST
  342.     */
  343. {
  344. char str[256];
  345. NAMES *name;
  346.  
  347.     if ( !write_define )
  348.         return;
  349.  
  350.     get_define_name(str);
  351.  
  352.     name=protocol_name(str,DEFINE);
  353.     if ( !name )
  354.         return;
  355.  
  356.     store_name(name,file,line,'D');
  357.  
  358.     fputs("#define ",dest);
  359.     fputs(buffer,dest);
  360.     fputs("\n\@endnode\n\n",dest);
  361. }
  362.  
  363. void copy_define(int *line)
  364.     /*
  365.         lese #define und kopiere in puffer
  366.         lese bis maximum von 
  367.             ende der zeile  oder
  368.             ende eines in der gleichen zeile beginnenden kommentars
  369.     */
  370. {
  371. enum {
  372.     C_READ,
  373.     C_COMM_1,
  374.     C_COMM_2,
  375.     C_COMM_3,
  376. } mode=C_READ;
  377. int com_cnt=0;
  378. int exit=0;
  379. char c;
  380.  
  381.     init_buffer();
  382.     do {
  383.         c=fgetc(source);
  384.     } while ( isspace(c) );
  385.     ungetc(c,source);
  386.  
  387.     do {
  388.         c=fgetc(source);
  389.         if ( c=='\n' )
  390.             (*line)++;
  391.  
  392.         switch ( mode ) {
  393.                 /* lese text */
  394.           case C_READ:
  395.             if ( c=='/' )             /* kommentar könnte anfangen */
  396.                 mode=C_COMM_1;
  397.             else if ( c=='\n' )
  398.                 exit=1;
  399.           break;
  400.  
  401.                 /* lese kommentar */
  402.           case C_COMM_1:
  403.               if ( c=='*' ) {
  404.                   com_cnt++;
  405.                   mode=C_COMM_2;
  406.             }
  407.               else {
  408.                   if ( com_cnt )
  409.                       mode=C_COMM_2;
  410.                 else if ( c!='/' )
  411.                       mode=C_READ;
  412.             }
  413.           break;
  414.           case C_COMM_2:
  415.               if ( c=='*' )
  416.                   mode=C_COMM_3;
  417.             else if ( c=='/' )
  418.                 mode=C_COMM_1;
  419.           break;
  420.           case C_COMM_3:
  421.             if ( c=='/' ) {
  422.                 com_cnt--;
  423.                 if ( com_cnt==0 ) {
  424.                     mode=C_READ;
  425.                 }
  426.                 else
  427.                     mode=C_COMM_2;
  428.             }
  429.             else if ( c!='*' )
  430.                 mode=C_COMM_2;
  431.           break;
  432.         }
  433.  
  434.         wr_buffer(c);
  435.     } while ( (!exit || com_cnt) && !feof(source) );
  436.     
  437.     wr_buffer(0);
  438. }
  439.  
  440. void get_fu_name(char *str)
  441.     /*
  442.         ermittle funktionsnamen
  443.             überliest rückwärts die Parameterliste
  444.             nimmt ersten folgenden namen
  445.     */
  446. {
  447. char *h;
  448. enum {
  449.     FU_READ,
  450.     FU_COM1,
  451.     FU_COM2,
  452.     FU_COM3,
  453.     FU_NAME,
  454.     FU_NAME2,
  455. } mode=FU_READ;
  456. int com_cnt=0,klammer=0;
  457. int exit=0;
  458.  
  459.     h=fu+strlen(fu);
  460.     do {
  461.         switch ( mode ) {
  462.           case FU_READ:
  463.               if ( *h=='/' )
  464.                   mode=FU_COM1;
  465.             else if ( *h==')' ) {
  466.                 klammer++;
  467.             }
  468.             else if ( *h=='(' ) {
  469.                 klammer--;
  470.                 if ( !klammer )
  471.                     mode=FU_NAME;
  472.             }
  473.           break;
  474.           case FU_COM1:
  475.               if ( *h=='*' ) {
  476.                   com_cnt++;
  477.                   mode=FU_COM2;
  478.               }
  479.               else {
  480.                   if ( com_cnt )
  481.                     mode=FU_COM2;
  482.                   else
  483.                       mode=FU_READ;
  484.             }
  485.           break;
  486.           case FU_COM2:
  487.               if ( *h=='/' )
  488.                   mode=FU_COM1;
  489.               else if ( *h=='*' )
  490.                   mode=FU_COM3;
  491.           break;
  492.           case FU_COM3:
  493.               if ( *h=='/' ) {
  494.                   com_cnt--;
  495.                   if ( !com_cnt )
  496.                       mode=FU_READ;
  497.                   else
  498.                       mode=FU_COM2;
  499.               }
  500.               else if ( *h!='*' )
  501.                   mode=FU_COM2;
  502.           break;
  503.           case FU_NAME:
  504.               if ( !isspace(*h) )
  505.                   mode=FU_NAME2;
  506.           break;
  507.           case FU_NAME2:
  508.               if ( !isalnum(*h) && *h!='_' )
  509.                   exit=1;
  510.           break;
  511.         }
  512.         if ( !exit )
  513.             h--;
  514.     } while ( !exit && h>=fu );
  515.  
  516.     h++;
  517.     while ( isalnum(*h) || *h=='_' )
  518.         *str++=*h++;
  519.     *str=0;
  520. }
  521.  
  522. void store_function(char *file,int line)
  523.     /*
  524.         schreibe funktion
  525.     */
  526. {
  527. char str[256];
  528. NAMES *name;
  529.  
  530.     if ( !write_function )
  531.         return;
  532.  
  533.     get_fu_name(str);
  534.  
  535.     name=protocol_name(str,FUNCTION);
  536.     if ( !name )
  537.         return;
  538.  
  539.     store_name(name,file,line,'F');
  540.  
  541.     fputs(fu,dest);
  542.     fputs("\n\@endnode\n\n",dest);
  543. }
  544.  
  545. void do_parse(char *file,int *line)
  546.     /*
  547.         lese quelle
  548.             'etwas' mißraten :-(
  549.     */
  550. {
  551. char c;
  552. enum {
  553.     M_READ,            /* zustände des automaten zur typedef-erkennung */
  554.     M_READ_SPACE,
  555.     M_READ_T,
  556.     M_READ_Y,
  557.     M_READ_P,
  558.     M_READ_E,
  559.     M_READ_D,
  560.     M_READ_E2,
  561.     M_READ_F,
  562.     M_COMM_1,
  563.     M_COMM_2,
  564.     M_COMM_3,
  565.     M_STRING,
  566.     M_STRING2,
  567.     M_CHARACTER,
  568.     M_CHARACTER2,
  569. } mode;
  570. int com_cnt=0;        /* verschachtelte kommentare */
  571.  
  572. enum {                /* zustände des automaten zur define-erkennung */
  573.     D_READ,            /*  wertet typedef-automaten-zustände mit aus */
  574.     D_READ_HASH,    /*  z.B. für kommentare/strings */
  575.     D_READ_D,
  576.     D_READ_E,
  577.     D_READ_F,
  578.     D_READ_I,
  579.     D_READ_N,
  580.     D_READ_E2,
  581. } dmode=D_READ;
  582.  
  583. enum {
  584.     F_READ,
  585.     F_PRAEPROC,
  586.     F_NAME,
  587.     F_FUNCTION_LIST,
  588.     F_FUNCTION,
  589.     F_FUTEXT,
  590. } fmode=F_READ;
  591. int name=0,block=0;
  592. char *_fu=fu;
  593. int copy=0;
  594. int klammer=0;
  595. int xline,xxline;
  596.  
  597.     mode=M_READ_SPACE;
  598.  
  599.     do {
  600.         c=fgetc(source);
  601.         if ( c=='\n' )
  602.             (*line)++;
  603.  
  604.             /*
  605.                 automat für erkennung von funktionen
  606.                         (muss vor automat für typedef stehen, 
  607.                          da dessen zustand wichtig)
  608.             */
  609.         if ( !com_cnt && mode!=M_STRING && mode!=M_STRING2 && mode!=M_CHARACTER && mode!=M_CHARACTER2 ) {
  610.             switch ( fmode ) {
  611.               case F_READ:
  612.                 if ( c=='{' ) {    /* } */
  613.                     block=1;
  614.                     fmode=F_FUTEXT;
  615.                 }
  616.                 if ( mode==M_READ_SPACE ) {
  617.                     if ( c=='#' )
  618.                         fmode=F_PRAEPROC;
  619.                     else if ( isalpha(c) || c=='_' ) {
  620.                         if ( !copy ) {
  621.                             _fu=fu;
  622.                             xxline=*line;
  623.                             copy=1;
  624.                         }
  625.                         name++;
  626.                         fmode=F_NAME;
  627.                     }
  628.                 }
  629.               break;
  630.               case F_PRAEPROC:
  631.                   if ( c=='\n' )
  632.                       fmode=F_READ;
  633.               break;
  634.               case F_NAME:
  635.                 if ( !(isalnum(c) || c=='_' || c=='*' || isspace(c))  ) {
  636.                     fmode=F_READ;
  637.                     if ( c=='(' ) {
  638.                         fmode=F_FUNCTION_LIST;
  639.                         klammer=1;
  640.                     }
  641.                     else {
  642.                         name=0;
  643.                         copy=0;
  644.                     }
  645.                 }
  646.                 else if ( isspace(c) )
  647.                     name++;
  648.               break;
  649.               case F_FUNCTION_LIST:
  650.                 if ( c=='(' )
  651.                     klammer++;
  652.                 else if ( c==')' ) {
  653.                     klammer--;
  654.                     if ( !klammer )
  655.                         fmode=F_FUNCTION;
  656.                 }
  657.               break;
  658.               case F_FUNCTION:
  659.                 if ( c=='{' ) {    /* } */
  660.                     if ( _fu>fu+buf_size )
  661.                         do_error(ERR_BUFFER);
  662.                     *_fu++=0;
  663.                     store_function(file,xxline);
  664.                     copy=0;
  665.                     name=0;
  666.                     block=1;
  667.                     fmode=F_FUTEXT;
  668.                 }
  669.                 else if ( !isspace(c) && c!='/' && c!='*' ) {
  670.                                     /* war wohl ein prototyp oder sonstwas */
  671.                     fmode=F_READ;
  672.                     copy=0;
  673.                     name=0;
  674.                 }
  675.                 break;
  676.               case F_FUTEXT:
  677.                 if ( c=='{' )
  678.                     block++;
  679.                 else if ( c=='}' ) {
  680.                     block--;
  681.                     if ( !block )
  682.                         fmode=F_READ;
  683.                 }
  684.             }
  685.  
  686.             /*
  687.                 automat für erkennung von defines
  688.                         (muss vor automat für typedef stehen, 
  689.                          da dessen zustand wichtig)
  690.             */
  691.     
  692.             switch ( dmode ) {
  693.               case D_READ:
  694.                 if ( mode==M_READ_SPACE && c=='#' ) {
  695.                     dmode=D_READ_HASH;
  696.                 }
  697.               break;
  698.               case D_READ_HASH:
  699.                 if ( c=='d' )
  700.                     dmode=D_READ_D;
  701.                 else if ( !isspace(c) || c=='\n' )
  702.                     dmode=D_READ;
  703.               break;
  704.               case D_READ_D:
  705.                 if ( c=='e' )
  706.                     dmode=D_READ_E;
  707.                 else if ( !isspace(c) || c=='\n' )
  708.                     dmode=D_READ;
  709.               break;
  710.               case D_READ_E:
  711.                 if ( c=='f' )
  712.                     dmode=D_READ_F;
  713.                 else if ( !isspace(c) || c=='\n' )
  714.                     dmode=D_READ;
  715.               break;
  716.               case D_READ_F:
  717.                 if ( c=='i' )
  718.                     dmode=D_READ_I;
  719.                 else if ( !isspace(c) || c=='\n' )
  720.                     dmode=D_READ;
  721.               break;
  722.               case D_READ_I:
  723.                 if ( c=='n' )
  724.                     dmode=D_READ_N;
  725.                 else if ( !isspace(c) || c=='\n' )
  726.                     dmode=D_READ;
  727.               break;
  728.               case D_READ_N:
  729.                 if ( c=='e' )
  730.                     dmode=D_READ_E2;
  731.                 else if ( !isspace(c) || c=='\n' )
  732.                     dmode=D_READ;
  733.               break;
  734.             }
  735.         }
  736.         if ( copy ) {
  737.             if ( _fu>fu+buf_size )
  738.                 do_error(ERR_BUFFER);
  739.             *_fu++=c;
  740.         }
  741.  
  742.         switch ( mode ) {
  743.  
  744.                 /* lese text */
  745.           case M_READ:
  746. /* { */        if ( isspace(c) || c==';' || c=='}' )        
  747.                 mode=M_READ_SPACE;        /* space... -> typedef könnte folgen */
  748.             else if ( c=='/' )        /* kommentar könnte anfangen */
  749.                 mode=M_COMM_1;
  750.             else if ( c=='"' )        /* string fängt an */
  751.                 mode=M_STRING;
  752.             else if ( c=='\'' )        /* char-const */
  753.                 mode=M_CHARACTER;
  754.           break;
  755.  
  756.                 /* lese kommentar */
  757.           case M_COMM_1:
  758.               if ( c=='*' ) {
  759.                   com_cnt++;
  760.                   mode=M_COMM_2;
  761.             }
  762.               else {
  763.                   if ( com_cnt )
  764.                       mode=M_COMM_2;
  765.                 else if ( c=='"' )
  766.                     mode=M_STRING;
  767.                 else if ( c=='/' )
  768.                     mode=M_COMM_1;
  769.                 else if ( isspace(c) )
  770.                     mode=M_READ_SPACE;
  771.                   else
  772.                       mode=M_READ;
  773.             }
  774.           break;
  775.           case M_COMM_2:
  776.               if ( c=='*' )
  777.                   mode=M_COMM_3;
  778.             else if ( c=='/' )
  779.                 mode=M_COMM_1;
  780.           break;
  781.           case M_COMM_3:
  782.             if ( c=='/' ) {
  783.                 com_cnt--;
  784.                 if ( com_cnt==0 )
  785.                     mode=M_READ_SPACE;
  786.                 else
  787.                     mode=M_COMM_2;
  788.             }
  789.             else if ( c!='*' )
  790.                 mode=M_COMM_2;
  791.           break;
  792.  
  793.                 /* lese string */
  794.           case M_STRING:
  795.               if ( c=='\\' )
  796.                   mode=M_STRING2;
  797.             else if ( c=='"' )
  798.                 mode=M_READ;
  799.           break;
  800.           case M_STRING2:
  801.             mode=M_STRING;
  802.           break;
  803.  
  804.                 /* lese char-const */
  805.           case M_CHARACTER:
  806.               if ( c=='\\' )
  807.                   mode=M_CHARACTER2;
  808.               else if ( c=='\'' )
  809.                   mode=M_READ;
  810.           break;
  811.           case M_CHARACTER2:
  812.               mode=M_CHARACTER;
  813.           break;
  814.  
  815.                 /* lese sukzessive <SPACE>typedef */
  816.           case M_READ_SPACE:
  817.               if ( c=='t' )
  818.                 mode=M_READ_T;
  819.             else if ( c=='/' )
  820.                 mode=M_COMM_1;
  821.             else if ( c=='"' )
  822.                 mode=M_STRING;
  823.             else if ( !isspace(c) )
  824.                 mode=M_READ;
  825.           break;
  826.           case M_READ_T:
  827.             if ( c=='y' )
  828.                 mode=M_READ_Y;
  829.             else if ( c=='"' )
  830.                 mode=M_STRING;
  831.             else if ( c=='/' )
  832.                 mode=M_COMM_1;
  833.             else if ( isspace(c) )
  834.                 mode=M_READ_SPACE;
  835.             else
  836.                 mode=M_READ;
  837.           break;
  838.           case M_READ_Y:
  839.             if ( c=='p' )
  840.                 mode=M_READ_P;
  841.             else if ( c=='"' )
  842.                 mode=M_STRING;
  843.             else if ( c=='/' )
  844.                 mode=M_COMM_1;
  845.             else if ( isspace(c) )
  846.                 mode=M_READ_SPACE;
  847.             else
  848.                 mode=M_READ;
  849.           break;
  850.           case M_READ_P:
  851.             if ( c=='e' )
  852.                 mode=M_READ_E;
  853.             else if ( c=='"' )
  854.                 mode=M_STRING;
  855.             else if ( c=='/' )
  856.                 mode=M_COMM_1;
  857.             else if ( isspace(c) )
  858.                 mode=M_READ_SPACE;
  859.             else
  860.                 mode=M_READ;
  861.           break;
  862.           case M_READ_E:
  863.             if ( c=='d' )
  864.                 mode=M_READ_D;
  865.             else if ( c=='"' )
  866.                 mode=M_STRING;
  867.             else if ( c=='/' )
  868.                 mode=M_COMM_1;
  869.             else if ( isspace(c) )
  870.                 mode=M_READ_SPACE;
  871.             else
  872.                 mode=M_READ;
  873.           break;
  874.           case M_READ_D:
  875.             if ( c=='e' )
  876.                 mode=M_READ_E2;
  877.             else if ( c=='"' )
  878.                 mode=M_STRING;
  879.             else if ( c=='/' )
  880.                 mode=M_COMM_1;
  881.             else if ( isspace(c) )
  882.                 mode=M_READ_SPACE;
  883.             else
  884.                 mode=M_READ;
  885.           break;
  886.           case M_READ_E2:
  887.             if ( c=='f' )
  888.                 mode=M_READ_F;
  889.             else if ( c=='"' )
  890.                 mode=M_STRING;
  891.             else if ( c=='/' )
  892.                 mode=M_COMM_1;
  893.             else if ( isspace(c) )
  894.                 mode=M_READ_SPACE;
  895.             else
  896.                 mode=M_READ;
  897.           break;
  898.         }
  899.  
  900.         if ( mode==M_READ_F ) {
  901.             xline=*line;
  902.             copy_typedef(line);
  903.             store_typedef(file,xline);
  904.             mode=M_READ_SPACE;
  905.             fmode=F_READ;
  906.             dmode=D_READ;
  907.             copy=0;
  908.             name=0;
  909.         }
  910.         else if ( dmode==D_READ_E2 ) {
  911.             xline=*line;
  912.             copy_define(line);
  913.             store_define(file,xline);
  914.             dmode=D_READ;
  915.             mode=M_READ_SPACE;
  916.             copy=0;
  917.             name=0;
  918.         }
  919.     } while ( !feof(source) );
  920.  
  921.     return;
  922. }
  923.  
  924. void make_xname(char *out,char *in)
  925.     /*
  926.         erzeuge absoluten dateinamen 'out' aus dem möglicherweise relativen 'in'
  927.     */
  928. {
  929.     if ( in[1]==':' )
  930.         strcpy(out,in);
  931.     else {
  932.         out[0]=Dgetdrv()+'A';
  933.         out[1]=':';
  934.         if ( *in=='\\' )
  935.             strcpy(out+2,in);
  936.         else {
  937.             Dgetpath(out+2,0);
  938.             strcat(out,"\\");
  939.             strcat(out,in);
  940.         }
  941.     }
  942. }
  943.  
  944. void do_file(char *name)
  945.     /*
  946.         bearbeite datei
  947.     */
  948. {
  949. int line;
  950. char xname[256];
  951.  
  952.     source=fopen(name,"r");
  953.     if ( !source )
  954.         return;
  955.     line=1;
  956.  
  957.     make_xname(xname,name);
  958.  
  959.     do_parse(xname,&line);
  960.  
  961.     fclose(source);
  962.     source=0l;
  963. }
  964.  
  965. int qsort_cmp(NAMES **n1,NAMES **n2)
  966. {
  967.     return strcmp((*n1)->name,(*n2)->name);
  968. }
  969.  
  970. void write_indizes(void)
  971.     /* 
  972.         schreibe index-seiten
  973.     */
  974. {
  975. int i,j,k,l;
  976. NAMES **index,*n;
  977. char types[]="FTD";
  978.  
  979.     for ( i=0; i<3; i++ ) {
  980.  
  981.         switch ( i ) {
  982.           case TYPEDEF:
  983.             fputs("@node Typ-Definitionen\n\n",dest);
  984.             fputs("@{B}Typ Definitionen@{b}\n\n",dest);
  985.           break;
  986.           case DEFINE:
  987.             fputs("@node Präprozessor-Definitionen\n\n",dest);
  988.             fputs("@{B}Präprozessor Definitionen@{b}\n\n",dest);
  989.           break;
  990.           case FUNCTION:
  991.             fputs("@node Funktionen\n\n",dest);
  992.             fputs("@{B}Funktionen@{b}\n\n",dest);
  993.           break;
  994.         }
  995.  
  996.         if ( name_count[i] ) {
  997.             index=calloc(name_count[i],sizeof(*index));
  998.             j=0;
  999.             for ( n=names; n->next!=0; n=n->next ) {
  1000.                 if ( n->typ==i ) {
  1001.                     index[j++]=n;
  1002.                 }
  1003.             }
  1004.             qsort(index,name_count[i],sizeof(*index),qsort_cmp);
  1005.             free(index);
  1006.     
  1007.             for ( j=0; j<name_count[i]; j++ ) {
  1008.  
  1009.                 l=24;
  1010.                 if ( index[j]->unique ) {
  1011.                     if ( index[j]->count ) {
  1012.                         l=22;
  1013.                         fprintf(dest,"@{%s.%d link %s.%d}",index[j]->name,index[j]->count,index[j]->name,index[j]->count);
  1014.                     }
  1015.                     else
  1016.                         fprintf(dest,"@{%s link %s}",index[j]->name,index[j]->name);
  1017.                 }
  1018.                 else {
  1019.                     if ( index[j]->count ) {
  1020.                         l=21;
  1021.                         fprintf(dest,"@{%s.%c%d link %s.%c%d}",index[j]->name,types[index[j]->typ],index[j]->count,index[j]->name,types[index[j]->typ],index[j]->count);
  1022.                     }
  1023.                     else {
  1024.                         l=22;
  1025.                         fprintf(dest,"@{%s.%c link %s.%c}",index[j]->name,types[index[j]->typ],index[j]->name,types[index[j]->typ]);
  1026.                     }
  1027.                 }
  1028.                 if ( !((j+1)%3) )
  1029.                     fputs("\n",dest);
  1030.                 else {
  1031.                     if ( strlen(index[j]->name)<l-2 )
  1032.                         for ( k=l-(int)strlen(index[j]->name); k>0; k-- )
  1033.                             fputs(" ",dest);
  1034.                     else
  1035.                         fputs("  ",dest);
  1036.                 }
  1037.             }
  1038.         }
  1039.         else {
  1040.             fputs("Keine Eintragungen",dest);
  1041.         }
  1042.         fputs("\n\n@endnode\n\n",dest);
  1043.     }
  1044. }
  1045.  
  1046. void write_filenames(int first,int last,char *names[])
  1047.     /* 
  1048.         schreibe dateinamen
  1049.     */
  1050. {
  1051. char str[256];
  1052. int i;
  1053.  
  1054.     fputs("@node Source-Files\n\n",dest);
  1055.     fputs("@{B}Source Files@{b}\n\n",dest);
  1056.     for ( i=first; i<last; i++ ) {
  1057.         make_xname(str,names[i]);
  1058.         fputs("  @{",dest);
  1059.         fputs(str,dest);
  1060.         fputs(" link ",dest);
  1061.         fputs(str,dest);
  1062.         fputs("/Main}\n",dest);
  1063.     }
  1064.     fputs("@endnode",dest);
  1065. }
  1066.  
  1067. int main(int argc,char *argv[])
  1068. {
  1069. int i,ii;
  1070. char c;
  1071.  
  1072.     printf("\nSHelp\n\n  Online-Hilfe zu C-Sourcen mit ST-Guide\n");
  1073.     printf("  V0.1 31.12.1994\n");
  1074.     printf("  written by Th. Morus Walter\n\n");
  1075.     if ( argc==1 ) {
  1076.         printf("Usage   : shelp [Optionen] File[s]\n");
  1077.         printf("Optionen: -d    : doppelte Referenzen jedesmal schreiben (.NR zur Kennung)\n");
  1078.         printf("          -sSIZE: Puffergröße für Namen angeben (in Kbyte), Default: 64\n");
  1079.         printf("          -bSIZE: Puffergröße für Strukturen/Funktionsköpfe angeben (in Kbyte)\n");
  1080.         printf("                  Default: 8\n");
  1081.         printf("          -hFILE: Headerfile angeben, Default: HEADER.STG\n");
  1082.         printf("          -oFILE: Outputfile angeben, Default: SDOKU.STG\n");
  1083.         printf("          -iTEXT: Database angeben, Default: \"Online-Hilfe zu C-Sourcen\"\n");
  1084.         printf("          -f    : Funktionsdeklarationen ausgeben\n");
  1085.         printf("          -t    : Typ-Definitionen (typedef) ausgeben\n");
  1086.         printf("          -p    : Präprozessor Definitionen ausgeben\n");
  1087.         printf("            ist weder -f noch -t noch -p gesetzt, so wird -f -t -p verwendet\n\n");
  1088.         return 1;
  1089.     }
  1090.  
  1091.     i=1;
  1092.     while ( *argv[i]=='-' ) {
  1093.         switch ( tolower(argv[i][1]) ) {
  1094.           case 'f':
  1095.             write_function=1;
  1096.           break;
  1097.           case 't':
  1098.             write_typedef=1;
  1099.           break;
  1100.           case 'p':
  1101.             write_define=1;
  1102.           break;
  1103.           case 's':
  1104.             sscanf(argv[i]+2,"%ld",&names_size);
  1105.             names_size*=1024;
  1106.           break;
  1107.           case 'b':
  1108.             sscanf(argv[i]+2,"%ld",&buf_size);
  1109.             buf_size*=1024;
  1110.           break;
  1111.           case 'd':
  1112.             dont_write_double=0;
  1113.           break;
  1114.           case 'h':
  1115.             strcpy(header_file,argv[i]+2);
  1116.           break;
  1117.           case 'o':
  1118.             strcpy(out_file,argv[i]+2);
  1119.           break;
  1120.           case 'i':
  1121.             strcpy(database,argv[i]+2);
  1122.           break;
  1123.           default:
  1124.             do_error(ERR_OPTIONS);
  1125.           break;
  1126.         }
  1127.         i++;
  1128.         if ( i==argc )
  1129.             break;
  1130.     }
  1131.  
  1132.     if ( i==argc )
  1133.         do_error(ERR_NOFILES);
  1134.  
  1135.     if ( write_function==0 && write_typedef==0 && write_define==0 )
  1136.         write_function=write_typedef=write_define=1;
  1137.  
  1138.     names=malloc(names_size);
  1139.     if ( !names )
  1140.         do_error(ERR_MEMORY);
  1141.     buffer=malloc(buf_size);
  1142.     if ( !buffer )
  1143.         do_error(ERR_MEMORY);
  1144.     fu=malloc(buf_size);
  1145.     if ( !fu )
  1146.         do_error(ERR_MEMORY);
  1147.  
  1148.     next=names;
  1149.     next->next=0l;
  1150.  
  1151.     dest=fopen(out_file,"w");
  1152.     if ( !dest )
  1153.         do_error(ERR_FILE);
  1154.  
  1155.     fputs("@database \"",dest);
  1156.     fputs(database,dest);
  1157.     fputs("\"\n",dest);
  1158.  
  1159.     source=fopen(header_file,"r");
  1160.     if ( source ) {
  1161.         c=fgetc(source);
  1162.         while ( !feof(source) ) {
  1163.             fputc(c,dest);
  1164.             c=fgetc(source);
  1165.         }
  1166.         fclose(source);
  1167.         source=0l;
  1168.     }
  1169.     ii=i;
  1170.     for ( ; i<argc; i++ ) {
  1171.         printf("bearbeite %s\n",argv[i]);
  1172.         do_file(argv[i]);
  1173.     }
  1174.  
  1175.     printf("schreibe Indexseiten\n");
  1176.     write_indizes();
  1177.     printf("schreibe Dateiliste\n");
  1178.     write_filenames(ii,argc,argv);
  1179.  
  1180.     fclose(dest);
  1181.     free(fu);
  1182.     free(buffer);
  1183.     free(names);
  1184.  
  1185.     return 0;
  1186. }
  1187.